# Joao Lencart e Silva: j.lencart@ua.pt
import os
from odcutils._etc import _parts
import fnmatch
import csv
from datetime import datetime, timedelta
import numpy
import operator

def probe(instrument, wildcard):
    """reads all input files matching the wildcard  and outputs a csv file with
    the_ following columns 'filename', 'nscans', 'date'. Implemented for SBE and
    RBR CTDs, DST milli-T* thermistor and the Minibat ondulator.
        Usage:
            wld = 'path/to/data/files/*.wildcard'
            inst_type = choose from ['SBE', 'RBR', 'DST', 'MB']
            probe(inst_type, wld)
    """
    fname = ['source_file']
    nscans = ['z']
    date_b = [':start_date']
    date_e = [':end_date']
    if instrument == 'IDR':
        cruise = [':cruise_ID']
        station = [':station_name']
        longitude = ['lon_dat']
        latitude = ['lat_dat']
        depth = [':water_depth']
        ddatum = [':pressure_offset']
    adir = os.path.abspath(os.path.dirname(wildcard))
    apat = os.path.basename(wildcard)
    # List the files
    filelist = fnmatch.filter(os.listdir(adir),apat)
    # Go through all the files
    for file in filelist:
        fname.append(os.path.join(adir,file))
    # Open dat file
        f1 = open(os.path.join(adir,file))
    # Dump all data into intermediate variable
        dump = f1.readlines()
    # Close dat file
        f1.close()
    # Call probe
        if instrument == 'SBE':
            ns, db, de = _sbeProbe(dump)
        elif instrument == 'RBR':
            ns, db, de = _rbrProbe(dump)
        elif instrument == 'DST':
            ns, db, de = _dstProbe(dump)
        elif instrument == 'MB':
            ns, db, de = _mbProbe(dump)
        elif instrument == 'IDR':
            ns, db, de, cru, sta, lon, lat, dep, ddat = _idrProbe(dump)
        else:
            print 'Probe for instrument of type ' + instrument + ' not\
                  implemented.\n'
            print 'Nothing done.\n'
            return
    # Append to variables
        nscans.append(ns)
        date_b.append(db)
        date_e.append(de)
        if instrument == 'IDR':
            cruise.append(cru)
            station.append(sta)
            longitude.append(lon)
            latitude.append(lat)
            depth.append(dep)
            ddatum.append(ddat)
    # Open csv file
    f1 = open(os.path.join(adir,'probe.csv'), 'w')
    # Create csv file writter object
    writer = csv.writer(f1)
    # Use zip to distribute items in the 4 variables into each row
    if instrument == 'IDR':
        L = zip(fname, nscans, date_b, date_e, cruise, station, longitude,\
                latitude, depth, ddatum)
    else:
        L = zip(fname, nscans, date_b, date_e)
    # Write into csv file
    writer.writerows(L)
    # Close csv file
    f1.close()

def _dstProbe(dump):
    """reads all dat files in directory and outputs a csv file with the_
    following columns 'filename', 'nscans', 'date'"""
    db = []
    de = []
    data = []
    # Find end of header
    for line in dump:
        if line[0] == '#': continue
        data.append(line)
    # First scan
    s = data[0].split()
    db = s[1] + s[2]
    do = datetime.strptime(db,'%d.%m.%y%H:%M:%S')
    db = do.strftime('%Y%m%d%H%M%S')
    # Last scan
    s = data[-1].split()
    de = s[1] + s[2]
    do = datetime.strptime(de,'%d.%m.%y%H:%M:%S')
    de = do.strftime('%Y%m%d%H%M%S')
    nscans = len(data)
    return nscans, db, de

def _rbrProbe(dump):
    """reads all dat files in directory and outputs a csv file with the_
    following columns 'filename', 'nscans', 'date'"""
    de = []
# Find timestamp
    timestamp = map(float, dump[0].split())[0]
#        print timestamp
# Create datetime object
    do = _parts.dNum2DTime(timestamp)
    date = do.strftime('%Y%m%d%H%M%S')
    nscans = len(dump)
    return nscans, date, de


def _sbeProbe(dump):
    """reads all cnv files in directory and outputs a csv file with the_
    following columns 'filename', 'nscans', 'date'"""
    de = []
    # Read timestamp
    for line in dump:
        if line.startswith('# start_time'):
            c = line.split()
            c = ''.join(c[3:])
    # Create datetime object
            do = datetime.strptime(c, '%b%d%Y%H:%M:%S')
            date = do.strftime('%Y%m%d%H%M%S')
    # Find header end and cut it
    # Try in windows and unix formats
    try:
        hd = dump.index('*END*\r\n')
    except ValueError:
        hd = dump.index('*END*\n')
    dump = dump[hd + 1:]
    nscans = len(dump)
    return nscans, date, de

def _idrProbe(dump):
    """Private parse function for IDRONAUT 320 in the Instituto Hidrografico
    Portugues (wwww.hidrografico.pt) format."""
    lonsign = {'E':1, 'W':-1}
    latsign = {'N':1, 'S':-1}
    de = []
    # Read timestamp
    for line in dump:
        if line.split()[0] == 'DATA:':
            c = line.split()
            c = c[1]+c[3]
    # Create datetime object
            do = datetime.strptime(c, '%Y-%m-%d%H:%M')
            date = do.strftime('%Y%m%d%H%M%S')
        elif line.split()[0] == 'CRUZEIRO:':
            cru = line.split()[1]
        elif line.split()[0] == 'ESTACAO:':
            sta = line.split()[1]
        elif line.split()[0] == 'LONGITUDE:':
            a = line.split()[1:4]
            lon = (float(a[0]) + float(a[1])/60)*lonsign[a[2]]
        elif line.split()[0] == 'LATITUDE:':
            a = line.split()[1:4]
            lat = (float(a[0]) + float(a[1])/60)*latsign[a[2]]
        elif line.split()[0] == 'SONDA':
            dep = float(line.split()[2])
        elif line.split()[1] == 'OFFSET':
            ddat = float(line.split()[3])
        else:
            continue
    # Find header end and cut it
    for l in range(0,len(dump)):
        if dump[l].split()[0] == 'hh:mm:ss.sss':
            break
    dump = dump[l + 1:]
    nscans = len(dump)

    return nscans, date, de, cru, sta, lon, lat, dep, ddat

def _mbProbe(dump):
    """reads all dat files in directory and outputs a csv file with the_
    following columns 'filename', 'nscans', 'date'"""
    s = []
    s.append(dump[0].split())
    s.append(dump[-1].split())
    flt = []
    flt.append(map(float, s[0]))
    flt.append(map(float, s[-1]))
    # Create datetime objects for the first day of the year of the timestamp
    dol = []
    dol.append(datetime(int(flt[0][0]), 1, 1))
    dol.append(datetime(int(flt[1][0]), 1, 1))
    # Create timedelta objects for each time stamp. Subtract 1 day to convert
    # between julian and yearday (1.0001 vs 0.0001 shortly after midnight 
    # January the 1st).
    dtl = []
    dtl.append(timedelta(days = flt[0][1] - 1))
    dtl.append(timedelta(days = flt[1][1] - 1))
    # Add timedelta to datetime objects
    dol = map(operator.add, dol,dtl)
    db = dol[0].strftime('%Y%m%d%H%M%S')
    de = dol[1].strftime('%Y%m%d%H%M%S')
    nscans = len(dump)
    return nscans, db, de
